home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
video
/
xevil-1.000
/
xevil-1
/
test.h
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-08
|
20KB
|
804 lines
/* Copyright (C) 1994 Steve Hardt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Steve Hardt
hardts@athena.mit.edu (or hardts@r4002.3dem.bioch.bcm.tmc.edu)
2043 McClendon
Houston, TX 77030
*/
#ifndef PHYSICAL_HH
#define PHYSICAL_HH
#pragma interface
// Include Files
#include "utils.h"
#include "coord.h"
#include "area.h"
#include "world.h"
#include "id.h"
#include "intel.h"
#include "locator.h"
// Defines
#define PH_ANIM_MAX 4
#define PH_FRAME_MAX 7
#define PH_WEAPONS_MAX 10
#define PH_ITEMS_MAX 20
#define PH_AMMO_UNLIMITED -1
#define PH_CORPSE_TIME 400
// Other declarations
enum PHsig {PH_NO_SIG, PH_NOT_SET, PH_ID_CHANGED};
// Class declarations
////////// Physical
/* The parent class of all physical objects. */
struct PhysicalContext {
Health health;
Mass mass;
ClassId classId;
const char *clas;
};
class Physical {
public:
Physical(const PhysicalContext &,WorldP,LocatorP);
/* EFFECTS: Create a new, mapped physical with no Id with undefined area. */
Physical();
/* NOTE: Should never be called. */
virtual ~Physical();
virtual const Area &get_area() = 0;
Health get_health() {return health;}
Health get_health_max() {return pc->health;}
Mass get_mass() {return mass;}
virtual Vel get_vel();
virtual Dir get_dir();
ClassId get_class_id() {return pc->classId;}
const char *identify() {return pc->clas;}
virtual int get_drawing_level();
Boolean delete_me() {return deleteMe;}
Boolean alive() {return health >= 0;}
/* NOTE: Is publicly known that (health >= 0) <=> alive. So this function is
just for convenience. */
/* Should only be used for abstract classes. Actual classes can be tested
for with get_class_id(). */
virtual Boolean is_moving();
virtual Boolean is_shot();
virtual Boolean is_item();
virtual Boolean is_bomb();
virtual Boolean is_weapon();
virtual Boolean is_cutter();
virtual Boolean is_gun();
virtual Boolean is_creature();
virtual Boolean is_user();
virtual Boolean is_fighter();
virtual Boolean is_walking();
virtual Boolean is_sticky();
virtual Boolean is_flying();
Boolean get_mapped() {return mapped;}
virtual Boolean collidable();
/* NOTE: This value never changes for an object. */
const Acc *get_unit_accs() {return unitAccs;}
const Vel *get_unit_vels() {return unitVels;}
Id get_id() {assert(idValid); return id;}
PHsig get_id(Id &id);
/* MODIFIES: id */
/* EFFECTS: Set id to be the Id and return PH_NO_SIG if set. Otherwise,
return PH_NOT_SET. */
PhysicalP get_dont_collide() {return dontCollide;}
/* EFFECTS: If there is another object that *this is not allowed to collide
with, return it. Otherwise return NULL; */
IntelP get_intel() {return intel;}
/* NOTE: Can be NULL. */
void set_command(ITcommand c) {command = c;}
/* EFFECTS: Sets the command to be c, overrides any previous command
setting. */
/* NOTE: command is not clocked. */
PHsig set_id(const Id &id);
/* EFFECTS: Set the Id to be id. Return PH_NO_SIG if there was no previous
id. Return PH_ID_CHANGED if there was a previous id. The id is set in
either case. */
void set_dont_collide(PhysicalP other) {dontCollide = other;}
/* EFFECTS: *this will not be allowed to collide with other. Any previous
value will be overridden. A setting of NULL disables this feature. */
void set_intel(IntelP i) {intel = i; if (i) i->set_id(id);}
/* REQUIRES: Object has been added to locator (has valid id.)
/* NOTE: Can be NULL. */
void set_health_next(Health h) {healthNext = h;}
virtual void set_mapped_next(Boolean val);
/* NOTE: Should be ok to set the value to the previous value. */
/* NOTE: idempotent */
/* Calls up the tree. */
void set_no_death_delete() {noDeathDelete = True;}
virtual void corporeal_attack(PhysicalP killer,int damage);
virtual void heat_attack(PhysicalP,int heat,Boolean secondary = False);
/* NOTE: Sometimes call up the tree. */
/* NOTE: killer is the one responsible for causing the damage. Can be
NULL. Adds kills to the killer. */
/* NOTE: Only the last call before the update cycle takes effect. */
virtual void avoid(PhysicalP);
virtual void collide(PhysicalP);
/* EFFECTS: Collision procedures. avoid is called on the lighter of the two
objects. collide is called on both objects. */
/* NOTE: Not always called up the tree. */
void intelligence() {if (intel) intel->clock(this);}
void kill_self() {healthNext = -1;}
virtual void set_quiet_death();
/* EFFECTS: When this dies, do not do any funny things like leaving corpses
or exploding or any other type of physical evidence. */
/* NOTE: Calls up the tree. */
void virtual act();
/* EFFECTS: Action phase. All next variables must be set here. Commands
are interpreted here.*/
void virtual update();
/* EFFECTS: Set current variables to be the next ones. No interactions
between physical objects. */
void virtual draw(Drawable buffer,Xvars &xvars, const Area &area) = 0;
/* REQUIRES: buffer is at least as big as area. */
/* EFFECTS: Draw the physical object in buffer. buffer represents area. */
/* NOTE: Does not check for overlap */
/* NOTE: X variables initialized in draw. Thus, if draw is never called for
a base class, the X variables never need to be initialized. */
void virtual die();
/* EFFECTS: If the *this dies a natural death (I.e. health < 0), then this
function is called. Not called if *this is
destroyed for any other reason. E.g. end of game. The default is to
kill the intel and set_delete_me. */
/* NOTE: Intel is created/destroyed by Game or Locator. */
/* NOTE: Should be called in update phase. */
/* NOTE: Calls up the tree. */
/* NOTE: Guaranteed to be called only once. */
virtual int get_weapons_num();
virtual int get_items_num();
/* NOTE: Returned value is not valid after current turn. */
virtual PhysicalP get_weapon(int);
virtual PhysicalP get_item(int);
virtual PhysicalP get_weapon_current();
virtual PhysicalP get_item_current();
/* NOTE: Can return NULL. */
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
WorldP get_world() {return world;}
Boolean alive_next() {return healthNext >= 0;}
LocatorP get_locator() {return locator;}
const ITcommand &get_command() {return command;}
/* EFFECTS: Gets the command. */
/* NOTE: command is not clocked. */
Boolean get_mapped_next() {return mappedNext;}
void set_mass_next(Mass mss) {massNext = mss;}
void set_delete_me() {deleteMe = True;}
private:
void init_static();
static Boolean staticValid;
static Acc unitAccs[CO_DIR_MAX];
static Vel unitVels[CO_DIR_MAX];
Boolean idValid;
Id id;
WorldP world;
LocatorP locator;
ITcommand command;
const PhysicalContext *pc;
Health health, healthNext;
Mass mass, massNext;
PhysicalP dontCollide;
IntelP intel;
Boolean deleteMe;
Boolean mapped,mappedNext;
Boolean noDeathDelete; // Should set_delete_me be called at death.
Boolean dieCalled;
int heat, heatNext;
Boolean previousHeatWasSecondary;
};
// PhysicalP defined in locator.h
////////// Moving
// Parent: Physical
// Has all 19 directions. Multiple pixmaps. Can change size and position.
// Top speed is VEL_MAX.
/* Only sizes[CO_air] and offsets[CO_air] are required to be set.
Gives initial size and offset. */
struct MovingContext {
char *foreColorName;
Boolean foreWhiteDefault;
const char *backColorName;
Boolean backWhiteDefault;
int animMax[CO_DIR_MAX];
Size sizes[CO_DIR_MAX];
Size offsets[CO_DIR_MAX];
char *pixmapBits[CO_DIR_MAX][PH_ANIM_MAX];
char *maskBits[CO_DIR_MAX][PH_ANIM_MAX];
PhysicalContext physicalContext;
};
class MovingXdata {
public:
MovingXdata() {valid = False;}
Boolean valid;
Pixmap pixmaps[CO_DIR_MAX][PH_ANIM_MAX],
masks[CO_DIR_MAX][PH_ANIM_MAX];
};
class Moving: public Physical {
public:
Moving(const MovingContext &m_c,
MovingXdata &x_data,
WorldP world,
LocatorP l,
const Pos &rawPos,
Dir dirInitial = CO_air);
Moving();
/* NOTE: Should never be called. */
virtual Boolean is_moving();
virtual const Area &get_area();
virtual Vel get_vel();
const Pos &get_raw_pos() {return rawPos;}
virtual Dir get_dir();
void set_middle_next(const Pos &pos);
/* EFFECTS: Sets the middle of pos according to the current (not next) values
of dir, and area (for size). */
/* NOTE: May be called before or after act phase. */
void set_extra_vel_next(const Vel &vel)
{extraVelNext = vel; extraVelNextSet = True;}
virtual void act();
virtual void update();
virtual void draw(Drawable,Xvars &,const Area &);
virtual void avoid(PhysicalP);
virtual void collide(PhysicalP);
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
Boolean hit_wall() {return hitWall;}
Boolean hit_wall_next() {return hitWallNext;}
Dir get_dir_next() {return dirNext;}
const Area &get_area_next() {return areaNext;}
const MovingContext *get_moving_context() {return mc;}
Vel get_vel_next() {return velNext;}
void set_vel(const Vel &v) {vel = v;}
void set_vel_next(const Vel &vel) {velNext = vel;}
void set_vel_next(int zero) {assert (zero == 0); velNext.set_zero();}
/* EFFECTS: Sets the next velocity for the object to be vel. Can be called
multiple times before update, only the last call is used. */
// void set_extra_vel(const Vel &vel) {extraVel = vel;}
/* NOTE: Not clocked. */
void set_dir(const Dir &d) {dir = d;}
/* NOTE: Only used by Lance for initialization. */
void set_dir_next(const Dir &d) {dirNext = d;}
void set_raw_pos_next(const Pos &rpos)
{rawPosNext = rpos; rawPosChanged = True;}
void update_next();
/* EFFECTS: Compute areaNext and hitWallNext. May modify rawPosNext or
dirNext. */
/* NOTE: May be called more than once per turn. */
virtual void get_pixmap_mask(Pixmap &pixmap,Pixmap &mask,
Dir dir,int animNum);
/* MODIFIES: pixmap, mask */
/* NOTE: Only used so that children of Moving can affect Moving's actions. */
virtual void get_size_offset_next(Size &size,Size &offset,Dir dirNext);
/* MODIFIES: size, offset */
/* NOTE: Only used so that children of Moving can affect Moving's actions. */
virtual void init_x(Xvars &);
/* NOTE: Now called up the tree. */
private:
Boolean context_valid();
/* EFFECTS: Returns True if this->cx is valid, False otherwise. */
float compute_collision(Mass m1,float v1,Mass m2,float v2);
MovingXdata *movingXdata;
int movingAnimNum;
Timer animTimer;
const MovingContext *mc;
Pos rawPos,rawPosNext; Boolean rawPosChanged;
Area area,areaNext;
Dir dir,dirNext;
Vel vel,velNext;
Boolean extraVelNextSet;
Vel extraVel,extraVelNext; // Follows clock in non-standard way.
Boolean hitWall,hitWallNext;
};
typedef Moving *MovingP;
////////// Shot
// Parent: Moving
struct ShotContext {
int damage; // Or heat.
Speed speed;
MovingContext movingContext;
};
typedef MovingXdata ShotXdata ;
class Shot: public Moving {
public:
Shot(const ShotContext &,ShotXdata &,WorldP,LocatorP,
const Pos &,const Id &shooter,
Dir shotDir,Dir movingDir = CO_air);
const Id &get_shooter() {return shooter;}
virtual Boolean is_shot();
virtual void avoid(PhysicalP other);
virtual void collide(PhysicalP other);
virtual void update();
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
int get_damage() {return context->damage;}
private:
Id shooter;
const ShotContext *context;
};
////////// Falling
// Parent: Moving
// Moving with gravity. Falls until it is blocked by the world.
struct FallingContext {
MovingContext movingContext;
};
typedef MovingXdata FallingXdata;
class Falling: public Moving {
public:
Falling(const FallingContext &h_c,FallingXdata &x_data,
WorldP world,LocatorP l,const Pos &rawPos,
Dir dirInitial = CO_air);
virtual void act();
};
//////////// Heavy
// Parent: Falling
// Does damage to things it lands on.
struct HeavyContext {
int damage;
FallingContext fallingContext;
};
typedef FallingXdata HeavyXdata;
class Heavy: public Falling {
public:
Heavy(const HeavyContext &h_c,
HeavyXdata &x_data,
WorldP world,
LocatorP l,
const Pos &rawPos);
virtual void collide(PhysicalP);
/* EFFECTS: Crush things it falls on. */
private:
const HeavyContext *context;
};
//////////// Generator
// Parent: Heavy
// Generate machines and register them with the locator.
struct GeneratorContext {
HeavyContext heavyContext;
};
typedef HeavyXdata GeneratorXdata;
class Generator: public Heavy {
public:
Generator(const IntelOptions &ops,ITmask opMask,
const char *prefix,
const GeneratorContext &g_c,
GeneratorXdata &x_data,
WorldP w,
LocatorP l,
const Pos &rawPos);
virtual void act();
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
virtual PhysicalP generate() = 0;
private:
enum {MAX = 10, TIME = 100};
Timer timer;
int machineCount; // Always increasing.
IntelOptions machineOps;
ITmask machineOpMask;
const char *machinePrefix;
Id generated[MAX];
const GeneratorContext *generatorContext;
};
//////////// Item
// Parent: Falling
//
struct ItemContext {
Boolean persists;
FallingContext fallingContext;
};
typedef FallingXdata ItemXdata;
class Item: public Falling {
public:
Item(const ItemContext &c_x,
ItemXdata &x_data,
WorldP w,
LocatorP l,
const Pos &pos);
Boolean is_item() {return True;}
Boolean is_held() {return held;}
Boolean can_take() {return canTake.ready() && !held && !cantTake;}
/* EFFECTS: Returns whether the object can be picked up. */
virtual int get_drawing_level();
/* NOTE: Items are at drawing level 1. */
Boolean persists() {return context->persists;}
virtual void follow_user(const Pos &userMiddle,Dir userDir);
void taken(PhysicalP);
/* EFFECTS: The object has been taken by another Physical. */
/* NOTE: Changes immediate externally visible state. Should only be called
in the collision phase. */
void dropped(PhysicalP);
/* EFFECTS: The object has been dropped by another Physical. */
/* NOTE: Called by another object in the act phase. */
/* NOTE: Called in either the act or update phase. */
/* NOTE: Calls up the tree. */
virtual void use(PhysicalP);
/* EFFECTS: p uses *this. */
/* NOTE: Called by another object in act phase. */
void set_used_message() {usedMessage = True;}
/* EFFECTS: On death, the printed message will say the item was used instead
of saying the item was destroyed. */
virtual void act();
virtual void die();
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
void set_cant_take() {cantTake = True;}
private:
Boolean held;
Boolean usedMessage;
Timer canTake;
Boolean cantTake;
const ItemContext *context;
};
typedef Item *ItemP;
//////////// Animated
// Parent: Item
//
struct AnimatedContext {
char *colorName;
Size size;
int animMax[PH_FRAME_MAX];
char *pixmapBits[PH_FRAME_MAX][PH_ANIM_MAX];
char *maskBits[PH_FRAME_MAX][PH_ANIM_MAX];
ItemContext itemContext;
};
class AnimatedXdata {
public:
AnimatedXdata() {valid = False;}
Boolean valid;
Pixmap pixmaps[PH_FRAME_MAX][PH_ANIM_MAX],
masks[PH_FRAME_MAX][PH_ANIM_MAX];
ItemXdata itemXdata;
};
class Animated: public Item {
public:
Animated::Animated(const AnimatedContext &,AnimatedXdata &,
WorldP,LocatorP,const Pos &);
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
void set_frame(Frame fr) {frame = fr;}
void set_frame_next(Frame fr) {frameNext = fr;}
Frame get_frame() {return frame;}
virtual void get_pixmap_mask(Pixmap &pixmap,Pixmap &mask,
Dir dir,int animNum);
virtual void get_size_offset_next(Size &size,Size &offset,
Dir dirNext);
virtual void init_x(Xvars &);
virtual void update();
private:
Boolean context_valid();
AnimatedXdata *animatedXdata;
const AnimatedContext *ac;
Frame frame,frameNext;
int animatedAnimNum;
};
//////////// Weapon
// Parent: Item
//
struct WeaponContext {
Boolean defaultable;
ItemContext itemContext;
};
typedef ItemXdata WeaponXdata;
class Weapon;
typedef Weapon *WeaponP;
class Weapon: public Item {
public:
Weapon(const WeaponContext &c_x,
WeaponXdata &x_data,
WorldP w,
LocatorP l,
const Pos &pos);
Boolean is_weapon() {return True;}
virtual Boolean ready() = 0;
/* EFFECTS: Can the weapon be fired now. */
/* NOTE: Sometimes calls up the tree.*/
Boolean defaultable() {return wc->defaultable;}
/* EFFECTS: Is this a type of weapon that can safely be set automatically as
the current weapon. E.g. You do not want to set a soul-swapper as the
current weapon unless the user explicitly says so. */
virtual int get_ammo() = 0;
virtual int get_ammo_max() = 0;
/* NOTE: Can return PH_AMMO_UNLIMITED. */
virtual void fire(const Id &id,ITcommand command);
/* REQUIRES: command is a weapon command. */
/* EFFECTS: Fire the weapon according to the specified command. id is the
physical firing the weapon. */
virtual void enter_scope_next(PhysicalP user);
virtual void leave_scope_next(PhysicalP user);
/* NOTE: Called during act(collide) or update phase. Should be just
act(). */
/* NOTE: Calls up the tree. */
/* NOTE: ok to call multiple times in same turn, but must enter/leave scope
in proper order. */
void take_ammo_from(WeaponP other);
/* EFFECTS: Take as much ammo as possible from the other weapon. */
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
Boolean entered_scope() {return enteredScope;}
virtual void set_ammo(int) = 0;
private:
const WeaponContext *wc;
Boolean enteredScope; // not clocked
};
// typedef Weapon *WeaponP; Defined above.
//////////// Cutter
// Parent: Weapon
// NOTE: Uses CO_center for cutter directly in front of user.
struct CutterContext {
int damage; // per turn
Size offsets[CO_DIR_MAX]; // From User's middle to Cutter's middle.
char *unheldColorName;
Size unheldSize;
char *unheldPixmapBits;
char *unheldMaskBits;
WeaponContext weaponContext;
};
class CutterXdata {
public:
CutterXdata() {valid = False;}
Boolean valid;
Pixmap unheldPixmap,unheldMask;
WeaponXdata weaponXdata;
};
class Cutter: public Weapon {
public:
Cutter(const CutterContext &c_x,CutterXdata &x_data,
WorldP w,LocatorP l,const Pos &pos);
virtual Boolean is_cutter();
virtual Boolean ready();
virtual int get_ammo();
virtual int get_ammo_max();
virtual void get_pixmap_mask(Pixmap &pixmap,Pixmap &mask,
Dir dir,int animNum);
virtual void get_size_offset_next(Size &size,Size &offset,Dir dirNext);
virtual void set_ammo(int);
virtual void follow_user(const Pos &,Dir);
virtual void enter_scope_next(PhysicalP);
virtual void leave_scope_next(PhysicalP);
virtual void collide(PhysicalP);
virtual void update();
#ifndef PROTECTED_IS_PUBLIC
protected:
#endif
virtual void init_x(Xvars &);
private:
Dir dir_4_from_user_dir(Dir);
Boolean inScope,inScopeNext;
Id killerId; // Valid iff inScope.
CutterXdata *cutterXdata;
const CutterContext *context;
};
#endif